package online.inote.naruto.utils.time;

import online.inote.naruto.utils.Assert;

import java.time.*;
import java.time.temporal.TemporalUnit;
import java.util.Date;

/**
 * @description 日期时间计算器
 * @author gaopengsui@creditease.cn
 * @date 2021/09/10 16:27
 */
public class Calculator {

  public static LocalDateTime getNow() {
    return LocalDateTime.now();
  }

  public static Date getNowDate() {
    return Converter.toDate(getNow());
  }

  public static LocalDate getNowLocalDate() {
    return LocalDate.now();
  }

  public static LocalTime getNowLocalTime() {
    return LocalTime.now();
  }

  /**
   * 加指定单位(年月日时分秒毫秒)指定步长
   *
   * @param date 日期
   * @param stepSize 步长
   * @return 结果
   */
  public static Date plus(Date date, long stepSize, TemporalUnit unit) {
    Assert.notNull(date, "date cannot be null");
    Assert.notNull(unit, "unit cannot be null");
    return Converter.toDate(Converter.toLocalDateTime(date).plus(stepSize, unit));
  }

  /**
   * 减指定单位(年月日时分秒毫秒)指定步长
   *
   * @param date 日期
   * @param stepSize 步长
   * @return 结果
   */
  public static Date minus(Date date, long stepSize, TemporalUnit unit) {
    Assert.notNull(date, "date cannot be null");
    Assert.notNull(unit, "unit cannot be null");
    return Converter.toDate(Converter.toLocalDateTime(date).minus(stepSize, unit));
  }

  public static DateTime endTime(LocalDateTime dateTime) {
    return new DateTime(dateTime.toLocalDate().atTime(endTimeOfDay()));
  }

  public static DateTime endTime(LocalDate date) {
    return new DateTime(date.atTime(endTimeOfDay()));
  }

  public static DateTime endTime(Date date) {
    return new DateTime(Converter.toLocalDate(date).atTime(endTimeOfDay()));
  }

  public static DateTime endTimeOfToday() {
    return new DateTime(getNowLocalDate().atTime(endTimeOfDay()));
  }

  public static DateTime endTimeOfThisWeek() {
    return new DateTime(getNowLocalDate().atTime(endTimeOfDay()));
  }

  /**
   * 结束时间 例如：23:59:59
   *
   * @return
   */
  public static LocalTime endTimeOfDay() {
    return LocalTime.MAX.withNano(0);
  }

  /**
   * 计算年龄(周岁)
   *
   * @param birthDay 出生日期
   * @return 结果
   */
  public static int getAge(LocalDate birthDay) {
    Assert.notNull(birthDay, "birthDay cannot be null");

    Period period = periodBetween(birthDay, LocalDate.now());

    if (period.getYears() < 0) {
      throw new DateTimeException("birthDay is after now!");
    } else {
      return period.getYears();
    }
  }

  /**
   * 计算年龄(周岁)
   *
   * @param birthDay 出生日期
   * @return 结果
   */
  public static int getAge(LocalDateTime birthDay) {
    return getAge(Converter.toLocalDate(birthDay));
  }

  /**
   * 计算年龄(周岁)
   *
   * @param birthDay 出生日期
   * @return 结果
   */
  public static int getAge(Date birthDay) {
    return getAge(Converter.toLocalDate(birthDay));
  }

  public static Period periodBetween(LocalDate startDateInclusive, LocalDate endDateExclusive) {
    return Period.between(startDateInclusive, endDateExclusive);
  }
}
